// 星星评分组件
import 'package:flutter/material.dart';

class StarRating extends StatefulWidget {
  // 当前评分、满分
  final double rating;
  final double maxRating;

  // 星星总数
  final int countStar;

  // 星星大小
  final double size;

  // 星星颜色
  final Color unselectedColor;
  final Color selectedColor;

  // 选中、未选中的星星
  final Widget selectedWidget;
  final Widget unSelectWidget;

  StarRating(
      {@required this.rating,
      this.maxRating = 10,
      this.countStar = 5,
      this.size = 30,
      // 默认值需要使用常量
      this.unselectedColor = const Color(0xffbbbbbb),
      this.selectedColor = const Color(0xffff0000),
      Widget selectWidget,
      Widget unSelectedWidget})
      : unSelectWidget = unSelectedWidget ??
            Icon(
              Icons.star_border,
              color: unselectedColor,
              size: size,
            ),
        selectedWidget = selectWidget ??
            Icon(
              Icons.star,
              color: selectedColor,
              size: size,
            );

  @override
  _StarRatingState createState() => _StarRatingState();
}

class _StarRatingState extends State<StarRating> {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        // 未选中的星星
        Row(
          mainAxisSize: MainAxisSize.min,
          children: _buildUnSelectedStar(),
        ),
        // 已选中星星
        Row(
          mainAxisSize: MainAxisSize.min,
          children: _buildSelectedStar(),
        )
      ],
    );
  }

  // 构建未选中的星星
  List<Widget> _buildUnSelectedStar() {
    return List.generate(widget.countStar, (index) {
      return widget.unSelectWidget;
    });
  }

  // 构建选中星星
  List<Widget> _buildSelectedStar() {
    List<Widget> stars = [];
    // 满星星
    Widget fullStar = widget.selectedWidget;
    // 计算全满星星的数量
    // 1.每颗星星代表的分数  10/5=2
    double oneStarScore = widget.maxRating / widget.countStar;
    // 2.当前获得的星星数量 5/2 = 2.5
    double ratingStar = widget.rating / oneStarScore;
    // 3.满星数量，向下取整 2
    int fullStarNum = ratingStar.floor();
    // 4.计算不满星的宽度
    double halfStarWidth = (ratingStar - fullStarNum) * widget.size;

    // 添加全满星
    for (int i = 0; i < fullStarNum; i++) {
      stars.add(fullStar);
    }

    // 添加半星,ClipRect 矩形裁剪 满星
    stars.add(ClipRect(
      child: fullStar,
      clipper: StarClipper(halfStarWidth),
    ));

    if (stars.length > widget.countStar) {
      stars = stars.sublist(0, widget.countStar);
    }

    return stars;
  }
}

class StarClipper extends CustomClipper<Rect> {
  final double clipWidth;

  StarClipper(this.clipWidth);

  // 获取裁剪矩形
  @override
  Rect getClip(Size size) {
    return Rect.fromLTRB(0, 0, clipWidth, size.height);
  }

  // 是否进行裁剪：当老的宽度不等于现在裁剪宽度时 进行裁剪
  @override
  bool shouldReclip(StarClipper oldClipper) {
    return oldClipper.clipWidth != clipWidth;
  }
}
